package com.dff.jrfw.dialog;

import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.OvershootInterpolator;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;

import com.dff.jrfw.R;
import com.dff.jrfw.utils.ToastUtil;

import java.security.KeyStore;
import java.text.MessageFormat;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

@RequiresApi(api = Build.VERSION_CODES.M)
public class BiometricIdentifyDialog extends Dialog {

    private ImageView iv;
    private ImageView iv2;
    private TextView sure;
    private TextView tv_error;
    CancellationSignal mCancellationSignal = new CancellationSignal();
    private KeyStore keyStore;
    private final static String DEFAULT_KEY_NAME = "default_key";
    private Cipher cipher;
    private final FingerprintManager fingerprintManager;
    private boolean success = false;
    private final CallBack callBack;

    public interface CallBack {
        void success();
        void onPrepared();
        void failure(String msg);
    }

    public BiometricIdentifyDialog(@NonNull Context context, CallBack callback) {
        super(context, R.style.CustomDialog);
        this.callBack = callback;
        setCanceledOnTouchOutside(false);   // 点击其他地方dialog不消失
        setCancelable(false);         // 点击返回键dialog不消失
        fingerprintManager = context.getSystemService(FingerprintManager.class);
        initKey();
        initCipher();
        callback.onPrepared();
    }

    // 初始化密钥库
    @RequiresApi(api = Build.VERSION_CODES.M)
    private void initKey() {
        try {
            keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);
            KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
            KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(DEFAULT_KEY_NAME,
                    KeyProperties.PURPOSE_ENCRYPT |
                            KeyProperties.PURPOSE_DECRYPT)
                    .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                    .setUserAuthenticationRequired(true)
                    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7);
            keyGenerator.init(builder.build());
            keyGenerator.generateKey();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // 初始化密钥
    private void initCipher() {
        try {
            SecretKey key = (SecretKey) keyStore.getKey(DEFAULT_KEY_NAME, null);
            cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
                    + KeyProperties.BLOCK_MODE_CBC + "/"
                    + KeyProperties.ENCRYPTION_PADDING_PKCS7);
            cipher.init(Cipher.ENCRYPT_MODE, key);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pop_biometric_identify);
        iv = findViewById(R.id.iv);
        iv2 = findViewById(R.id.iv2);
        sure = findViewById(R.id.tv_sure);
        tv_error = findViewById(R.id.tv_error);
        sure.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCancellationSignal.cancel();
                dismiss();
            }
        });
        if (callBack != null) {
            setOnDismissListener(new OnDismissListener() {
                @Override
                public void onDismiss(DialogInterface dialog) {
                    if (success) {
                        callBack.success();
                    } else {
                        callBack.failure(tv_error.getText().toString());
                    }
                }
            });
        }
    }

    @Override
    public void show() {
        success = false;
        fingerprintManager.authenticate(new FingerprintManager.CryptoObject(cipher), mCancellationSignal, 0, new FingerprintManager.AuthenticationCallback() {
            @Override
            public void onAuthenticationError(int errorCode, CharSequence errString) {
                super.onAuthenticationError(errorCode, errString);
                tv_error.setText(errString);
                dismiss();
            }

            @Override
            public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
                super.onAuthenticationHelp(helpCode, helpString);
                ToastUtil.toast(helpString.toString());
            }

            @Override
            public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
                super.onAuthenticationSucceeded(result);
                success = true;
                dismiss();
            }

            @Override
            public void onAuthenticationFailed() {
                super.onAuthenticationFailed();
                iv2.clearAnimation();
                TranslateAnimation animation = new TranslateAnimation(-5, 5, 0, 0);
                animation.setInterpolator(new OvershootInterpolator());
                animation.setDuration(30);
                animation.setRepeatCount(3);
                animation.setRepeatMode(Animation.REVERSE);
                animation.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {
                        iv.setVisibility(View.INVISIBLE);
                        iv2.setVisibility(View.VISIBLE);
                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        iv.setVisibility(View.VISIBLE);
                        iv2.setVisibility(View.GONE);
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {

                    }
                });
                iv2.startAnimation(animation);;
            }
        }, null);
        super.show();
    }
}
